package com.rorochen.server.gotty;

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.concurrent.atomic.AtomicBoolean;

public class GottyEventLoop implements EventLoop{

//    是否唤醒
    private AtomicBoolean wakeup=new AtomicBoolean(false);

    private Selector selector;

    private LinkedList<ChainHandler> chainHandlerLinkedList=new LinkedList<>();


    public GottyEventLoop() throws IOException {
        this.selector=Selector.open();
    }


    @Override
    public void handler(SelectionKey key)  {
        try{
            if( key.isReadable()  ){
                SocketChannel sc = (SocketChannel) key.channel();
                ByteBuffer buf= ByteBuffer.allocate(1000);
                int readLength=0;
                StringBuilder sb=new StringBuilder();
                while ( (readLength=sc.read(buf))>0){
                    buf.flip();
                    byte[] temp=new byte[buf.limit()];
                    buf.get(temp,0,readLength);
                    sb.append(new String(temp));
                    buf.clear();

                }

                if(readLength>=0){
//                    System.out.println("接收来自："+sc.getRemoteAddress()+" 消息："+sb.toString());
                    String response=sb.toString();
                    key.attach(response);

                    key.interestOps(  SelectionKey.OP_WRITE );
                }else {
                    key.cancel();
                    sc.close();
                }
            }
            if(key.isWritable()  ){
                SocketChannel sc = (SocketChannel) key.channel();
                String response= (String) key.attachment();
                int total=response.getBytes().length;
                ByteBuffer buf= ByteBuffer.allocate(total);
                buf.put(response.getBytes());
                buf.flip();
                int len=0;
                while ( !(total == 0) ) {
                    len=sc.write(buf);
                    total-=len;
                }
                System.out.println("向："+sc.getRemoteAddress()+" 发送消息："+response);
                key.cancel();
                sc.close();
//                key.interestOps( SelectionKey.OP_READ );
            }
        }catch (Exception e){
            key.cancel();
            e.printStackTrace();
        }



    }

    @Override
    public void close() {

    }

    @Override
    public void register(SelectableChannel var1) throws ClosedChannelException {
        this.setWakeUp(true);
        this.selector.wakeup();
        var1.register(this.selector,SelectionKey.OP_READ);
        this.setWakeUp(false);
    }


    public void setWakeUp(boolean nVal){
        if(!nVal){
            this.wakeup.set(false);
        }else {
            for(;!this.wakeup.compareAndSet(false,true);){

            }
        }

    }





    @Override
    public void run() {
        for(;;){
            for(;!wakeup.get();){
                try {
                    int r=this.selector.select();
                    if( wakeup.get() ){
                        break;
                    }
                    if( r>0){
                        Iterator<SelectionKey> it = this.selector.selectedKeys().iterator();
                        while(it.hasNext()) {
                            SelectionKey key = it.next();
                            it.remove();
                            this.handler(key);


                        }
                    }



                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }

    }
}
